﻿using DomainNameServer;
using DomainNameServer.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DSVISUAL.LocalDNS
{
    public partial class HostsImportForm : Form, IAcceptableFormBody
    {
        private bool closing;

        public HostsImportForm()
        {
            InitializeComponent();
            this.CenterToParent();
            this.FormClosing += HostsImportForm_FormClosing;
            var windowsPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
            this.button1.Text = Path.Combine(windowsPath, "System32\\drivers\\etc\\hosts");
        }

        private void HostsImportForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason != CloseReason.WindowsShutDown)
            {
                if ((this.AcceptButton as Button).Enabled == false && this.DialogResult != DialogResult.OK)
                {
                    e.Cancel = true;
                    MessageBox.Show(this, "please wait the request end...");
                }
            }
        }

        public void Accept(AcceptFormOption option)
        {
            (this.AcceptButton as Button).Enabled = false;
            var url = this.textBox1.Text;

            try
            {
                string[] lines = null;
                var fileUri = new Uri(url);
                if (fileUri.IsFile)
                {
                    lines = this.Invoke(new Func<string, string[]>((f) =>
                     {
                         var d = new OpenFileDialog();
                         d.FileName = f;
                         var r = d.ShowDialog();
                         if (r == DialogResult.OK)
                         {
                             return File.ReadAllLines(d.FileName);
                         }
                         else
                         {
                             return null;
                         }
                     }), url) as string[];
                    if (lines == null)
                        return;
                    handleLine(lines);
                }
                else
                {
                    WebClient c = new WebClient();
                    {
                        c.DownloadStringCompleted += C_DownloadStringCompleted;
                        c.DownloadStringAsync(new Uri(url));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "ERROR");
                this.Invoke(new Action(() =>
                {
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }));
            }
        }

        private void C_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
                MessageBox.Show(e.Error.Message, "ERROR");
            var str = e.Result;
            var lines = str.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
            handleLine(lines);
        }

        void handleLine(string[] lines)
        {
            foreach (var item in lines)
            {
                if (item.StartsWith("#") || item.StartsWith(":"))
                {
                    continue;
                }
                var pair = item.Split(new string[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
                if (pair.Length != 2)
                {
                    continue;
                }
                if (pair[1].IndexOf(".") == -1)
                    continue;
                var ip = pair[0];
                var addr = pair[1];
                var domain = DomainUtil.GetDomain("http://" + addr);
                if (domain.IndexOf(".") == -1)
                    continue;
                var idx = DomainManager.Instance.GetDomains().FindIndex(x => x.Domain == domain.ToLower());
                if (idx == -1)
                {
                    var d = (DomainInfo)this.Invoke(new Func<DomainInfo>(() => { return DomainManager.Instance.AddDomain(domain.ToLower()); }));
                    if (addr == domain)
                    {
                        //A Record
                        d.AddRecord(ARSoft.Tools.Net.Dns.RecordType.A, "@", ip);
                        continue;
                    }
                    idx = DomainManager.Instance.GetDomains().Count - 1;
                }
                //CNAME
                var prefix = addr.Replace(domain, "").TrimEnd('.');
                var recordA = DomainManager.Instance.GetDomains()[idx].RecordList.Find(r => r.RecordType == ARSoft.Tools.Net.Dns.RecordType.A && (r.Host == "@" || r.Host == "*"));
                var idx2 = DomainManager.Instance.GetDomains()[idx].RecordList.FindIndex(r => r.RecordType == ARSoft.Tools.Net.Dns.RecordType.CName && r.Host == prefix);
                if (idx2 == -1)
                {
                    if (recordA != null && recordA.ResoluteTo == ip)
                    {
                        DomainManager.Instance.GetDomains()[idx].AddRecord(ARSoft.Tools.Net.Dns.RecordType.CName, prefix, domain);
                    }
                    else
                    {
                        DomainManager.Instance.GetDomains()[idx].AddRecord(ARSoft.Tools.Net.Dns.RecordType.A, prefix, ip);
                    }
                }
            }
            var appData = StorageService.Instance.GetData<AppData>();
            appData.DomainList = DomainManager.Instance.GetDomains();
            StorageService.Instance.SaveData(appData);

            this.Invoke(new Action(() =>
            {
                MessageBox.Show("Operation Successful");
                this.DialogResult = DialogResult.OK;
                this.Close();
            }));
        }

        public void Cancel()
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = this.button1.Text;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = this.button2.Text;
        }
    }
}
